/****************************************************************************
*
*					Functions of class TripletXYYFeature
*
****************************************************************************/

#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <stdlib.h>

#include "DataSet.h"
#include "TripletXYYFeature.h"
#include "ExtendedPGMStruct.h"


/****************************************************************************
*					TripletXYYFeature::TripletXYYFeature
*
*	Description:	Standard constructor with initialization of internal variables
*	Parameters:		-
*	Returns:		-
*
****************************************************************************/
TripletXYYFeature::TripletXYYFeature (void) {
	this->clear();
	this->id = 2;
	this->name.assign("TripletXYY");
}


/****************************************************************************
*					TripletXYYFeature::~TripletXYYFeature
*
*	Description:	Standard destructor with removing all dynamic internal variables
*	Parameters:		-
*	Returns:		-
*
****************************************************************************/
TripletXYYFeature::~TripletXYYFeature (void) {
	
}


/****************************************************************************
*					TripletXYYFeature::calculate
*
*	Description:	Calculates feature value given variable domain and the data
*	Parameters:		varIDs - indexes of variables in 'vars' for which to 
*							 calculate the feature value
*					vars - all variables in the PGM
*	Returns:		0 - if features is not true (values of variables in PGM are
*						different from 'varValues')
*					1 - otherwise
*
****************************************************************************/
float TripletXYYFeature::calculate (const std::vector<unsigned int>& varIDs, const std::vector <unsigned int>& vars) const {
	if (varIDs.size() != 3) {
		std::cerr << "Error in TripletXYYFeature::calculate: TripletXYY feature is defined for 3 variables only.";
		return -1;
	}
	if ( (vars[varIDs[0]] == 2) && (vars[varIDs[1]] == 2) && (vars[varIDs[2]] == 2) )
		return 1.0;
	return 0.0;
}


/****************************************************************************
*					TripletXYYFeature::calculate
*
*	Description:	Calculates feature value given variable domain and the data
*	Parameters:		vars - variables for which to calculate feature value
*	Returns:		0 - if features is not true (values of variables in PGM are
*						different from 'varValues')
*					1 - otherwise
*
****************************************************************************/
float TripletXYYFeature::calculate (const std::vector <unsigned int>& vars) const {
	if (vars.size() != 3) {
		std::cerr << "Error in TripletXYYFeature::calculate: TripletXYY feature is defined for 2 variables only.";
		return -1;
	}
	if ( (vars[0] == 2) && (vars[1] == 2) && (vars[2] == 2) )
		return 1.0;
	return 0.0;
}


/****************************************************************************
*					TripletXYYFeature::calculate
*
*	Description:	Calculates feature value given PGM description
*	Parameters:		extPGMStruct - description of PGM to work on
*					varID - id of a variable in extPGMStruct for which (for which
*					nieghbors or local structure) to calculate the feature
*	Returns:		float - feature value in local network of variable varID
*						in extPGMStruct
*
****************************************************************************/
float TripletXYYFeature::calculate (const ExtendedPGMStruct& extPGMStruct, const unsigned int& varID) const {
	bool isX;
	unsigned int i, j, k;
	float FeatureValue = 0.0;
	extPGMStruct.getVarIndex(isX, i, j, varID);
	if ((!isX) || (extPGMStruct.variables[varID] != 2))
		return 0.0;
	// TripletXYY between three actors i, j and k: variables Xij, Yik, Yjk
	for (k = 0; k < extPGMStruct.nActors; k++) {
		// choose a distinct actor k (not equal to i or j)
		if (k == i)
			continue;
		if (k == j)
			continue;
		// check if both Yik and Yjk are active
		if ( (extPGMStruct.variables[extPGMStruct.getVarID(false, i, k)] == 2) && (extPGMStruct.variables[extPGMStruct.getVarID(false, j, k)] == 2) )
			FeatureValue++;
	}
	return FeatureValue / (float) extPGMStruct.nActors;
}


/****************************************************************************
*					TripletXYYFeature::setDesiredValues
*
*	Description:	Sets values for which a feature should return 1
*	Parameters:		desiredValues - ordered vector of desired values
*	Returns:		0
*
****************************************************************************/
int TripletXYYFeature::setDesiredValues (const std::vector <unsigned int>& desiredValues) {
	// Not applicable to this class - not doing anything
	return 0;
}


/****************************************************************************
*					TripletXYYFeature::getDesiredValues
*
*	Description:	Returns values for which a feature gives 1
*	Parameters:		desiredValues - a parameter that is set to the feature's
*						desired values of a domain of variables
*	Returns:		-1
*
****************************************************************************/
int TripletXYYFeature::getDesiredValues (std::vector <unsigned int>& desiredValues) const {
	// Not applicable to this class - returning empty vector
	desiredValues.clear();
	return -1;
}


/****************************************************************************
*					TripletXYYFeature::getObjectID
*
*	Description:	Returns ID of this type of features
*	Parameters:		-
*	Returns:		int - id of this class
*
****************************************************************************/
int TripletXYYFeature::getObjectID (void) const {
	return this->id;
}


/****************************************************************************
*					TripletXYYFeature::getObjectName
*
*	Description:	Returns string Name of this type of features
*	Parameters:		name - name of this class
*	Returns:		0
*
****************************************************************************/
int TripletXYYFeature::getObjectName (std::string &nameStr) const {
	nameStr = this->name;
	return 0;
}


/****************************************************************************
*					TripletXYYFeature::clear
*
*	Description:	Removes all variables in object internal variables
*	Parameters:		-
*	Returns:		-
*
****************************************************************************/
void TripletXYYFeature::clear (void) {
	
}


/****************************************************************************
*					TripletXYYFeature::operator==
*
*	Description:	Operator for checking whether two featres are the same
*	Parameters:		-
*	Returns:		-
*
****************************************************************************/
bool TripletXYYFeature::operator==(Feature& second) const {
	if (this->id != second.getObjectID())
		return false;	
	return true;
}
